package dancrawler.server.events;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 */
public class EventDirector {

    private HashMap<Class, ArrayList<EventHandler>> handlers = new HashMap<>();
    private BlockingQueue<Event> events = new LinkedBlockingQueue<>();

    public void addEventHandler(EventHandler h) {
        Class hc = h.getClass();
        for (Method m : hc.getMethods()) {
            if (m.getName().equals("handleEvent")) {
                Class[] params = m.getParameterTypes();
                if (params.length == 1 && Event.class.isAssignableFrom(params[0])) {
                    ArrayList<EventHandler> hl = handlers.get(params[0]);
                    if (hl == null) {
                        hl = new ArrayList<>();
                        handlers.put(params[0], hl);
                    }
                    hl.add(h);

                }
            }
        }
    }
    
    public void removeHandler(EventHandler eh)
    {
        handlers.remove(eh);
    }

    public void postEvent(Event ev) {
        events.offer(ev);
    }

    public void processEvents() {
        Event ev;
        while ((ev = events.poll()) != null) {
            ArrayList<EventHandler> hl = handlers.get(ev.getClass());
            if (hl != null) {
                for (EventHandler h : hl) {
                    if (h != null) {
                        try {
                            h.getClass().getMethod("handleEvent", ev.getClass()).invoke(h, ev);

                        } catch (NoSuchMethodException | SecurityException |
                                IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
                            System.out.println("Strange exception");
                        }
                    }
                }
            }
        }
    }
}
